/*******************************************************************************
 * file  : mem alloc cfg
 * creat : apleilx
 * data  : 2021/09/26
 *******************************************************************************/
#include "mem_alloc.h"
#include "sys_init.h"
#include "os_obj.h"
#include "framework.h"

/*******************************************************************************
 * @brief  config
 *******************************************************************************/
#define SRAM_MALLOC 1
#define CCM_MALLOC 1
#define ERAM_MALLOC 0
#define BLK_RAM_MALLOC 1

/*******************************************************************************
 * @brief  fun
 *******************************************************************************/
#if SRAM_MALLOC + CCM_MALLOC + BLK_RAM_MALLOC + ERAM_MALLOC > 0

static uu16 mem_ram_lock(void);
static void mem_ram_unlock(void);

/*******************************************************************************
 * @brief  ram opt lock
 * \param[in] none
 * \retval: os error
 *******************************************************************************/
static uu16 mem_ram_lock(void)
{
	uu16 st;

	if (osOK == osMutexWait(os_obj.mid_malloc, ms_ticks(2000)))
		st = 0;
	else
		st = 1;

	return st;
}

/*******************************************************************************
 * @brief  ram opt unlock
 * \param[in] none
 * \retval: os error
 *******************************************************************************/
static void mem_ram_unlock(void)
{
	osMutexRelease(os_obj.mid_malloc);
}

#endif

/*******************************************************************************
 * @brief  创建内存池 SRAM.
 *******************************************************************************/
#if SRAM_MALLOC > 0

#define SRAM_SIZE (96 * 1024UL)
#define SRAM_BLOCK_SIZE (128UL)
OBJ_ALIGN(256)
uu64 sram_map[SRAM_SIZE / 8] /*OBJ_SECTION(".sram")*/;				 // 内存池
uu16 sram_tab[SRAM_SIZE / SRAM_BLOCK_SIZE] /*OBJ_SECTION(".sram")*/; // 内存分配表
multi_malloc_info_type sram_info = {0};								 // 工作信息
multi_malloc_api_ref(mem_sram);										 // 接口引用声明
const multi_malloc_type mem_sram = {								 // 信息描述
	sram_map,
	sram_tab,
	SRAM_SIZE,
	SRAM_BLOCK_SIZE,
	SRAM_SIZE / SRAM_BLOCK_SIZE,
	mem_ram_lock,
	mem_ram_unlock,
	&sram_info,
	multi_malloc_api_name(mem_sram)};
multi_malloc_api_make(mem_sram); // 创建API接口

#endif

/*******************************************************************************
 * @brief  创建内存池 CCM.
 *******************************************************************************/
#if CCM_MALLOC > 0

#define CCM_SIZE (64)
#define CCM_BLOCK_SIZE (8)

uu64 ccm_map[CCM_SIZE / 8] OBJ_SECTION(".ccm");				 // 内存池
uu16 ccm_tab[CCM_SIZE / CCM_BLOCK_SIZE] OBJ_SECTION(".ccm"); // 内存分配表
multi_malloc_info_type ccm_info = {0};						 // 工作信息
multi_malloc_api_ref(mem_ccm);								 // 接口引用声明
const multi_malloc_type mem_ccm = {							 // 信息描述
	ccm_map,
	ccm_tab,
	CCM_SIZE,
	CCM_BLOCK_SIZE,
	CCM_SIZE / CCM_BLOCK_SIZE,
	mem_ram_lock,
	mem_ram_unlock,
	&ccm_info,
	multi_malloc_api_name(mem_ccm)};
multi_malloc_api_make(mem_ccm); // 创建API接口

#endif

/*******************************************************************************
 * @brief  创建内存池 EXT RAM.
 *******************************************************************************/
#if ERAM_MALLOC > 0

#define ERAM_SIZE (1024 * 1024)
#define ERAM_BLOCK_SIZE (512)

#define eram_map (uu64 *)SRAM_BASE_ADDR							 // 内存池
uu16 eram_tab[ERAM_SIZE / ERAM_BLOCK_SIZE] OBJ_SECTION(".eram"); // 内存分配表
multi_malloc_info_type eram_info = {0};							 // 工作信息
multi_malloc_api_ref(mem_eram);									 // 接口引用声明
const multi_malloc_type mem_eram = {							 // 信息描述
	eram_map,
	eram_tab,
	ERAM_SIZE,
	ERAM_BLOCK_SIZE,
	ERAM_SIZE / ERAM_BLOCK_SIZE,
	mem_ram_lock,
	mem_ram_unlock,
	&eram_info,
	multi_malloc_api_name(mem_eram)};
multi_malloc_api_make(mem_eram); // 创建API接口

#endif

/*******************************************************************************
 * @brief  创建块内存池.
 *******************************************************************************/
#if BLK_RAM_MALLOC > 0

#define AMEM_BLK1_SIZE 20
#define AMEM_BLK1_NUM 0x40

#define AMEM_BLK2_SIZE 40
#define AMEM_BLK2_NUM 0x40

#define AMEM_BLK3_SIZE 80
#define AMEM_BLK3_NUM 0x40

#define MEM_BLK1_SIZE 132
#define MEM_BLK1_NUM 0x40

#define MEM_BLK2_SIZE 260
#define MEM_BLK2_NUM 0x20

#define MEM_BLK3_SIZE 0x520
#define MEM_BLK3_NUM 0x10

#define MEM_BLK4_SIZE 0x1080
#define MEM_BLK4_NUM 4

#define MEM_BLK_BASE (0x20000000 + 0x50000)
#define MEM_BLK1_BASE MEM_BLK_BASE
#define MEM_BLK2_BASE (MEM_BLK1_BASE + MEM_BLK1_SIZE * MEM_BLK1_NUM)
#define MEM_BLK3_BASE (MEM_BLK2_BASE + MEM_BLK2_SIZE * MEM_BLK2_NUM)
#define MEM_BLK4_BASE (MEM_BLK3_BASE + MEM_BLK3_SIZE * MEM_BLK3_NUM)
#define MEM_BLK_END (MEM_BLK4_BASE + MEM_BLK4_SIZE * MEM_BLK4_NUM - 1)
#if MEM_BLK_END >= MEM_BLK_BASE + 60 * 1024
#error MEM BLOCK ADDRESS LIMIT OUT !
#endif

mem_blk_gen(blk_sram);

mem_blk_add(blk_sram, AMEM_BLK1_SIZE, AMEM_BLK1_NUM, 01);
mem_blk_add(blk_sram, AMEM_BLK2_SIZE, AMEM_BLK2_NUM, 02);
mem_blk_add_sec(blk_sram, AMEM_BLK3_SIZE, AMEM_BLK3_NUM, 03, "sram");

mem_blk_add_addr(blk_sram, MEM_BLK1_SIZE, MEM_BLK1_NUM, 04, MEM_BLK1_BASE);
mem_blk_add_addr(blk_sram, MEM_BLK2_SIZE, MEM_BLK2_NUM, 05, MEM_BLK2_BASE);
mem_blk_add_addr(blk_sram, MEM_BLK3_SIZE, MEM_BLK3_NUM, 06, MEM_BLK3_BASE);
mem_blk_add_addr(blk_sram, MEM_BLK4_SIZE, MEM_BLK4_NUM, 07, MEM_BLK4_BASE);

mem_blk_ext_cfg_make(blk_sram, mem_ram_lock, mem_ram_unlock);

/*******************************************************************************
 * @brief: fun
 ******************************************************************************/
int blk_sram_info(int argc, char *argv[]);
void mem_blk_info(mem_block_ext_cfg_type *ecfg);

/*******************************************************************************
 * @brief: 块内存信息打印.
 * @param argc 参数数量
 * @param argv 参数指针
 * @return 错误代码
 ******************************************************************************/
int blk_sram_info(int argc, char *argv[])
{
	mem_blk_info(&blk_sram);

	return 0;
}
DBG_FUN_EXPORT(blk_sram_info);

/*******************************************************************************
 * @brief: 块内存信息打印.
 * @param ecfg 内存内存配置
 * @return none
 ******************************************************************************/
void mem_blk_info(mem_block_ext_cfg_type *ecfg)
{
	mem_block_cfg_type *const *cfg = ecfg->cfg;
	uu32 total = 0, mark_len;

	dbg_print("=======================BLOCK MEM INFO===========================\n");
	cfg++;
	for (; *cfg; cfg++)
	{
		mem_block_cfg_type *cfg_sel = *cfg;
		mark_len = (cfg_sel->block_num + 15) >> 4;

		dbg_print("BLK BASE: %8X, BLK SIZE: %4d, BLK NUM: %3d, USED:%3d, ",
				  (uu32)(cfg_sel->mem_base),
				  cfg_sel->block_size,
				  cfg_sel->block_num,
				  cfg_sel->info->used);
		dbg_u16_print("MARK: ", cfg_sel->mem_mark, mark_len, mark_len + 1);
		total += cfg_sel->block_num * cfg_sel->block_size;
	}
	dbg_print("==================BLOCK MEM INFO END: %dKB=======================\n", total >> 10);
}
#endif
